
/**
 * Kohive.controllers.MembersController
 * @extends ExtMVC.Controller
 * Manages invitation of Members
 */
Kohive.controllers.MembersController = function() {
	Kohive.controllers.MembersController.superclass.constructor.call(this, {
				viewsPackage	: Kohive.controllers.MembersController.views
			});

	var os = ExtMVC.OS.getOS();
	var controller = this;

	this.registerViews({
				'memberSummary'		: Kohive.MemberSummary,
				'memberOptions'		: Kohive.MemberOptions,
				'memberPanel'		: Kohive.MemberPanel,
				'addMemberPanel'	: Kohive.views.members.New
			});

	this.addEvents(
			/**
	 * @event beforecreatemember
	 * Fires before a new Member object is saved.  Return false to cancel creation
	 * @param {Kohive.models.Member} hive The Member about to be created
	 */
			'beforecreatemember',

			/**
			 * @event membercreated
			 * Fires after successful creation of a new Member
			 * @param {Kohive.models.Member} Member The newly created Member
			 */
			'membercreated',

			/**
			 * @event creatememberfailed
			 * Fires if creation of a new Member failed for any reason.
			 * Return false with a listener to provide your own handling of this event, otherwise
			 * it defaults to showing an error message to the user
			 * @param {Kohive.models.Member} hive A Member model object which could not be saved
			 */
			'creatememberfailed',

			/**
			 * @event membersloaded
			 * Fires when the members are loaded for a hive
			 */
			'membersloaded'
	);

	// Add events to be handled
	this.handleEvent(os.memberPanel, 'new', 'new', this);

	this.handleEvent(os.memberOptions, 'acceptmember', 'acceptMember', this);
	this.handleEvent(os.memberOptions, 'rejectmember', 'rejectMember', this);
	this.handleEvent(os.memberOptions, 'cancelmember', 'cancelMember', this);

	this.handleEvent(os.memberOptions, 'kickmember', 'destroyMember', this);

	this.initListeners();

	/**
	 * Displays the Add Member panel, anchored above a specific Ext.Button.  Intended to be attached
	 * to the click event of the Add Member button on the MemberPanel.
	 * @action addMember
	 * @param {Ext.Button} btn The Ext.Button to align the Add Member panel over.  This will probably
	 * always be the Add Member button, sitting in the MemberPanel.specials container
	 */
	this.registerAction('new', function(btn, firstHive) {
				var btn = Kohive.OS.getMemberPanel().newButton;

				var v = this.getRunningView('addMemberPanel');

				var offset = [0, -15];

				if (!v) {
					// not rendered yet. Render now and show + align on render
					v = this.renderView('addMemberPanel', {
								hidden		: true,
								firstHive	: firstHive,
								listeners	: {
									'render'	: {
										fn	: function() {
											this.showHUD(offset);
										}
									}
								}
							});

					v.hide();

					this.handleEvent(v, 'cancel', 'cancelAddMember', this);
					this.handleEvent(v, 'save', 'addMember', this);
					this.handleEvent(v, 'find-contacts', 'findContacts', this);
				} else {
					v.showHUD(offset);
				};
			});

	/**
	 * @action addMember 
	 * Invites or requests a new member into a hive
	 */
	this.registerAction('addMember', function(addMemberPanel) {
				if (!addMemberPanel)
					return;

				// Call the startSave method which disables the form
				addMemberPanel.startSave();

				// Get the values of the form
				var values = {
					'email'		: Ext.get('new_member_email').getValue(),
					'hive_id'	: os.getCurrentHive().data.hive.id
				};

				// Create a new membership from the above values
				var membership = new Kohive.models.Membership(values);

				// Attempt to save the membership to the server
				membership.save({
							success		: function() {
								// Call the onsuccess method when it succeeds and reload the memberslist
								addMemberPanel.onSuccess();
								controller.fireAction('loadMembers');
							},
							failure		: function(modelObj) {
								// Call the onfailure method when there is a problem and pass it the errors
								addMemberPanel.onFailure(modelObj);
							},
							callback	: function() {
								// Call the endsave method once the response comes back
								addMemberPanel.endSave();
							}
						});
			});

	/**
	 * @action findContacts
	 * 
	 * @param {Ext.Panel} addMemberPanel The add member panel
	 * @param {String} email The email to use
	 * @param {String} service The service to use
	 */
	this.registerAction('findContacts', function(email, password, service) {
				var contact = {
					service		: service,
					login		: email,
					password	: password
				};

				// dispatch the invite controller
				Kohive.OS.dispatch({
							controller	: 'invite',
							action		: 'index'
						}, null, [contact]);
			});

	this.registerAction('sendMessage', function(membership, el) {
				this.createNewMessageBubble(membership, el);
			});

	this.registerAction('loadMessages', function() {
		if (this.fireEvent('before-ping') === false)
			return;

		// get the messages
		var msgs = Kohive.models.Message.findAll({
			url			: Kohive.OS.scopedUrl('messages'),
			listeners	: {
				scope	: this,
				'load'	: function(store) {
					// now the messages have loaded, show the first one and mark it as read
					var msg = store.getAt(0);
					if (!msg)
						return Kohive.OS.un('before-ping',
								Kohive.OS.returnFalse, Kohive.OS
						);

					// mark the message as read
					msg.update({
								read	: true
							}, {
								url		: '/memberships/'
										+ msg.get('assignee_membership_id')
										+ '/messages/' + msg.get('id'),
								failure	: function() {
									Ext.Msg
											.alert(
													'',
													'401:'
															+ Ext.ux.Translator
																	.translate('something_wrong')
											);
									Kohive.OS.un('before-ping',
											Kohive.OS.returnFalse, Kohive.OS
									);
								}
							}
					);

					// show the message
					// get the member button
					var panel = Kohive.OS.getMemberPanel(), nodes = panel
							.getNodes();

					if (msg.get('hive_id') == Kohive.OS.getCurrentHiveId()) {
						Ext.each(nodes, function(node) {
									var record = panel.getRecord(node);

									// check what the author_membership_id is
									if (record.get('id') == msg
											.get('author_membership_id')) {
										// get the el
										var el = Ext.get(node);

										// make the node
										this.createMessageBubble(el, msg);
									} else {
										Kohive.OS.un('before-ping',
												Kohive.OS.returnFalse,
												Kohive.OS
										);
									};
								}, this);
					} else {
						// find the hive to anchor to it
						var el = null;
						Kohive.OS.getHivePanel().items.each(function(item) {
									if (item.hive.id == msg.get('hive_id'))
										el = item.el;
								}, this);

						if (!el)
							return Kohive.OS.un('before-ping',
									Kohive.OS.returnFalse, Kohive.OS
							);

						// make the node
						this.createMessageBubble(el, msg, true);
					};
				}
			}
		}
		);
	}
	);

	/**
	 * Attempts to accept a pending member request.
	 * @action acceptInvite
	 * @param {Kohive.views.members.Button} btn The member button object
	 */
	this.registerAction('acceptMember', function(options) {
				var member = options.record;
				if (member == null)
					return;

				// Fire off the accept request method and override the success method
				member.update(values, {
							url		: this.getAcceptUrl(),
							success	: function() {
								controller.fireAction('loadMembers');
							},
							failure	: function() {
								Ext.Msg
										.alert(
												'Accept Invite',
												'303:'
														+ Ext.ux.Translator
																.translate('something_wrong')
										);
							}
						}
				);
			}
	);

	/**
	 * Attempts to accept a pending member request.
	 * @action inviteMember
	 * @param {Kohive.views.members.Button} btn The member button object
	 */
	this.registerAction('inviteMember', function(member, hive, btn) {
		if (!member || !hive)
			return;

		// Get the values of the form
		var values = {
			'id_card_id'	: member.get('id_card_id'),
			'hive_id'		: hive.id
		};

		// Create a new membership from the above values
		var membership = new Kohive.models.Membership(values);

		// Attempt to save the membership to the server
		membership.save({
			success		: function() {
				// Call the onsuccess method when it succeeds and reload the memberslist
				// controller.fireAction('loadMembers');
			},
			failure		: function(modelObj) {
				var isOwner = Kohive.OS.getCurrentUser().get('id') == hive.owner_id;
				if (!isOwner) {
					Ext.Msg
							.alert(
									'',
									Ext.ux.Translator
											.translate('add_member_max_reached_member')
							);
				} else {
					Ext.Msg.alert('', Ext.ux.Translator
									.translate('add_member_max_reached_owner'));
				};
			},
			callback	: function() {
				// Call the endsave method once the response comes back
				// addMemberPanel.endSave();
				btn.removeClass('add');
			}
		}
		);
	}
	);

	/**
	 * Rejects a pending member invite.
	 * @action rejectMember
	 * @param {Kohive.views.members.Button} btn The member button object
	 */
	this.registerAction('rejectMember', function(options) {
		var member = options.record;
		if (member == null)
			return;

		var rejectFn = function(btn) {
			if (btn == 'yes') {
				// Fire off the accept request method and override the success method
				member.update({}, {
							url		: member.getRejectUrl(),
							success	: function() {
								controller.fireAction('loadMembers');
							},
							failure	: function() {
								Ext.Msg
										.alert(
												'Reject Invite',
												'304:'
														+ Ext.ux.Translator
																.translate('something_wrong')
										);
							}
						}
				);
			};
		};

		return Ext.Msg.show({
					title	: '',
					msg		: Ext.ux.Translator.translate(
							'reject_inivitation_desc', {
								full_name	: member.get('id_card').full_name
										|| member.get('id_card').email,
								hive_title	: Kohive.OS.getCurrentHive()
										.get('title')
							}
					),
					buttons	: {
						yes	: Ext.ux.Translator.translate('decline'),
						no	: Ext.ux.Translator.translate('cancel')
					},
					fn		: rejectFn
				});
	}
	);

	/**
	 * Cancels a pending member invite.
	 * @action cancelMember
	 * @param {Kohive.views.members.Button} btn The member button object
	 */
	this.registerAction('cancelMember', function(options) {
		var member = options.record;
		if (!member)
			return;

		var cancelFn = function(btn) {
			if (btn == 'yes') {
				// Fire off the accept request method and override the success method
				member.destroy({
							success	: function() {
								controller.fireAction('loadMembers');
							},
							failure	: function() {
								Ext.Msg
										.alert(
												'Cancel Invite',
												'305:'
														+ Ext.ux.Translator
																.translate('something_wrong')
										);
							}
						}
				);
			};
		};

		return Ext.Msg.show({
					title	: '',
					msg		: Ext.ux.Translator.translate(
							'cancel_inivitation_desc', {
								full_name	: member.get('id_card').full_name
										|| member.get('id_card').email
							}
					),
					buttons	: {
						yes	: Ext.ux.Translator.translate('uninvite'),
						no	: Ext.ux.Translator.translate('keep')
					},
					fn		: cancelFn
				});
	}
	);

	/**
	 * Attempts to kick a member from a hive
	 * @action destroyMember
	 * @param {Kohive.views.members.Button} btn The member button object
	 */
	this.registerAction('destroyMember', function(options) {
		var member = options.record || null;
		if (member == null) {
			return;
		};

		var destroyFn = function(btn) {
			if (btn == 'yes') {
				// Fire off the accept request method and override the success method
				member.destroy({
					success	: function() {
						// TODO animate
						controller.fireAction('loadMembers');
					},
					failure	: function() {
						// if the member is yourself, display a different message
						if (member.get('user_id') == Kohive.OS.getCurrentUser()
								.get('id')) {
							return Ext.Msg
									.alert(
											Ext.ux.Translator
													.translate('leave_hive'),
											'317:'
													+ Ext.ux.Translator
															.translate('something_wrong')
									);
						};

						Ext.Msg.alert(Ext.ux.Translator
										.translate('kick_member'),
								'Sorry, we could not kick this member. Please try again.'
						);
					}
				}
				);
			};
		};

		// if the member is yourself, display a different message
		if (member.data.id_card.user_id == Kohive.OS.getCurrentUser().data.id) {
			return Ext.Msg.show({
				title	: Ext.ux.Translator.translate('leave_hive'),
				msg		: Ext.ux.Translator.translate('leave_hive_desc', {
							hive_title	: Kohive.OS.getCurrentHive().data.hive.title
						}
				),
				buttons	: {
					yes	: Ext.ux.Translator.translate('leave'),
					no	: Ext.ux.Translator.translate('stay')
				},
				fn		: destroyFn
			}
			);
		};

		return Ext.Msg.show({
					title	: Ext.ux.Translator.translate('kick_member'),
					msg		: Ext.ux.Translator.translate('kick_member_desc', {
								full_name	: member.data.id_card.nickname
										|| member.data.id_card.email
							}),
					buttons	: {
						yes	: Ext.ux.Translator.translate('kick_out'),
						no	: Ext.ux.Translator.translate('keep')
					},
					fn		: destroyFn
				});
	}
	);

	/**
	 * Hides the add member panel
	 * @action cancelAddMember
	 * @param {Ext.Panel} addMemberPanel The add member panel which fired the event
	 */
	this.registerAction('cancelAddMember', function(addMemberPanel) {
				addMemberPanel.hide();
			});

	/**
	 * Hides the member panel form view
	 */
	this.registerAction('beforeLoadMembers', function() {
				var memberPanel = memberPanel || Kohive.OS.getMemberPanel();

				Kohive.OS.getApplicationLauncher().hideView();
				memberPanel.hideView();
			});

	/**
	 * Refreshes the contents of the global Member Panel.  
	 * @param {Ext.Panel} memberPanel The global Member Panel object
	 * @param {Boolean} force True if you want to skip check differences
	 */
	this.registerAction('loadMembers', function(memberPanel) {
		if (!Kohive.OS.getCurrentHive())
			return;

		var memberPanel = memberPanel || Kohive.OS.getMemberPanel();

		Kohive.models.Membership.findAll({
					url			: '/hives/' + Kohive.OS.getCurrentHiveId()
							+ '/memberships',
					listeners	: {
						'load'	: {
							scope	: this,
							fn		: function(store, records, options) {
								Kohive.OS.log('Hive Memberships Store: loaded');
								Kohive.OS.getController('members').loaded = true;
								Kohive.OS.showMembersAndApplications(
										memberPanel, null, store
								);

								var memberships = [];
								store.each(function(record) {
											memberships.push(record);
										}, this);
								Kohive.OS
										.setCurrentHiveMemberships(memberships);

								// fire off the members loaded event
								// Kohive.OS.membersLoaded = true;
								memberPanel.fireEvent('membersloaded', this);
							}
						}
					}
				}
		);
	}
	);
};
Ext.extend(Kohive.controllers.MembersController, ExtMVC.Controller, {
	loaded					: false,

	/**
	 * 
	 */
	initListeners			: function() {
		Kohive.OS.getController('idcards').on({
			scope					: this,
			'update'				: this.fireAction.createDelegate(this, [
							'loadMembers', this, [null, true]]),
			'hive-id-card-update'	: this.fireAction.createDelegate(this, [
							'loadMembers', this, [null, true]])
		}
		);

		Kohive.OS.on({
					scope				: this,
					'beforehiveload'	: this.fireAction.createDelegate(this,
							['beforeLoadMembers', this]
					),
					'hiveload'			: this.fireAction.createDelegate(this,
							['loadMembers', this]
					)
				});
	},

	createNewMessageBubble	: function(membership, el) {
		Kohive.OS.on('before-ping', Kohive.OS.returnFalse, Kohive.OS);

		var bubble = new Ext.ux.HUD({
			anchorToEl		: el,
			title			: Ext.ux.Translator.translate('send_message_to_x',
					{
						assignee	: membership.get('id_card').nickname
					}
			),
			width			: 200,
			items			: [{
				layout	: 'column',
				items	: [{
							id			: 'hud_new_messages_field',
							bodyStyle	: 'margin:1px;',
							xtype		: 'field',
							allowBlank	: false,
							width		: 160
						}, {
							bodyStyle	: 'text-align:right;background:transparent;border:0;padding-left:3px;',
							items		: [new Kohive.IconButton({
										id		: 'hud_new_messages_icon_add',
										iconCls	: 'send'
									})]
						}]
			}],
			cls				: 'message',
			clickListener	: function(e) {
				if (!e.getTarget('.x-hud-wrapper')) {
					this.destroy();
					Kohive.OS.un('before-ping', Kohive.OS.returnFalse,
							Kohive.OS
					);
				};
			},
			startSave		: function() {
				this.disable();
				this.saving = true;

				// Find the form mask and create a loading animation child within it
				var mask = this.el.child('.ext-el-mask');
				if (mask) {
					mask.setHeight(this.el.getHeight());
					mask.setWidth(this.el.getWidth() - 3);
					mask.anchorTo(this.el, 'b-b', [1, -1]);

					this.loadingContainer = mask.createChild({
								cls	: 'x-loading'
							});

					this.loadingContainer.anchorTo(mask, 'c-c', [0, -3]);
				};
			},
			endSave			: function() {
				if (this.loadingContainer)
					this.loadingContainer.remove();

				this.enable();
				this.saving = false;
			}
		}
		);

		// render the hud
		bubble.render();

		// add icon
		var field = Ext.getCmp('hud_new_messages_field');
		var icon = Ext.get('hud_new_messages_icon_add');
		icon.enableDisplayMode();

		var submitFn = function() {
			var field = Ext.getCmp('hud_new_messages_field');
			var value = field.getValue();

			// check if the field is valid
			if (field.isValid()) {
				field.disable();
				bubble.startSave();

				var message = new Kohive.models.Message({
							body					: value,
							read					: false,
							hive_id					: Kohive.OS
									.getCurrentHiveId(),
							author_membership_id	: Kohive.OS
									.getCurrentHive().get('id'),
							assignee_membership_id	: membership.get('id')
						});

				message.save({
							url			: '/memberships/'
									+ Kohive.OS.getCurrentHive().get('id')
									+ '/messages',
							callback	: function() {
								bubble.endSave();
							},
							success		: function() {
								bubble.destroy();
								Kohive.OS.un('before-ping',
										Kohive.OS.returnFalse, Kohive.OS
								);
							},
							failure		: function() {
								field.enable();
							}
						});
			};
		};

		field.on('specialkey', function(e) {
					var key = Ext.EventObject.getKey();
					if (key === 13)
						submitFn();
				}, this);
		icon.on('click', submitFn, this);

		// hide the hud
		bubble.hide();

		// show the hud
		bubble.showHUD([0, -15], 'b-t', 1, function() {
					bubble.positionPoker([0, 0], 't-b');

					Ext.get('hud_new_messages_field').focus();
				}, true);
	},

	createMessageBubble		: function(el, msg, hive) {
		Kohive.OS.on('before-ping', Kohive.OS.returnFalse, Kohive.OS);

		var bubble = new Ext.ux.HUD({
			anchorToEl		: el,
			title			: Ext.ux.Translator.translate('message_from_x', {
						assignee	: msg.get('author_nickname')
					}),
			width			: 200,
			items			: [{
						id		: 'hud_messages_body',
						html	: msg.get('body')
					}, {
						id		: 'hud_messages_column',
						layout	: 'column',
						items	: [{
									id			: 'hud_messages_field',
									bodyStyle	: 'margin:1px;',
									xtype		: 'field',
									allowBlank	: false,
									width		: 160
								}, {
									bodyStyle	: 'text-align:right;background:transparent;border:0;padding-left:3px;',
									items		: [new Kohive.IconButton({
												id		: 'hud_messages_iconb',
												iconCls	: 'send'
											})]
								}]
					}, {
						bodyStyle	: 'text-align:right;background:transparent;padding-top:5px;',
						items		: [new Kohive.IconButton({
									id		: 'hud_messages_icon',
									iconCls	: 'reply'
								})]
					}],
			cls				: (hive === true) ? 'add-hive message' : 'message',
			pokerHeight		: 44,
			clickListener	: function(e) {
				if (!e.getTarget('.x-hud-wrapper')) {
					this.destroy();
					Kohive.OS.un('before-ping', Kohive.OS.returnFalse,
							Kohive.OS
					);
				};
			},
			startSave		: function() {
				this.disable();
				this.saving = true;

				// Find the form mask and create a loading animation child within it
				var mask = this.el.child('.ext-el-mask');
				if (mask) {
					mask.setHeight(this.el.getHeight() - 15);
					mask.setWidth(this.el.getWidth() - 3);
					mask.anchorTo(this.el, 't-t', [1, -1]);

					this.loadingContainer = mask.createChild({
								cls	: 'x-loading'
							});

					this.loadingContainer.anchorTo(mask, 'c-c', [0, -3]);
				};
			},
			endSave			: function() {
				if (this.loadingContainer)
					this.loadingContainer.remove();

				this.enable();
				this.saving = false;
			}
		}
		);

		// render the hud
		bubble.render();

		// field
		var field = Ext.get('hud_messages_field');
		field.enableDisplayMode();

		var columns = Ext.get('hud_messages_column');
		columns.enableDisplayMode();
		columns.hide();

		// add icon
		var icon = Ext.get('hud_messages_icon');
		var iconb = Ext.get('hud_messages_iconb');
		icon.enableDisplayMode();
		iconb.enableDisplayMode();

		var submitFn = function() {
			var field = Ext.getCmp('hud_messages_field');
			var value = field.getValue();

			// check if the field is valid
			if (field.isValid()) {
				field.disable();
				bubble.startSave();

				var message = new Kohive.models.Message({
					body					: value,
					read					: false,
					hive_id					: msg.get('hive_id'),
					author_membership_id	: msg.get('assignee_membership_id'),
					assignee_membership_id	: msg.get('author_membership_id')
				}
				);

				message.save({
							url			: '/memberships/'
									+ msg.get('assignee_membership_id')
									+ '/messages',
							callback	: function() {
								bubble.endSave();
								Kohive.OS.un('before-ping',
										Kohive.OS.returnFalse, Kohive.OS
								);
							},
							success		: function() {
								bubble.destroy();
							},
							failure		: function() {
								field.enable();
							}
						});
			};
		};

		var fielda = Ext.getCmp('hud_messages_field');
		fielda.on('specialkey', function(e) {
					var key = Ext.EventObject.getKey();
					if (key === 13)
						submitFn();
				}, this);

		iconb.on('click', submitFn, this);

		// body
		var body = Ext.get('hud_messages_body');
		body.enableDisplayMode();

		var bodyHeight = body.getHeight();
		var fieldHeight = field.getHeight();

		var difference = bodyHeight - fieldHeight;

		// btn
		var btn = Ext.get('hud_messages_icon');
		btn.on('click', function() {
					if (columns.isVisible()) {
						icon.show();
						body.show();
						columns.hide();

						bubble.setTitle(Ext.ux.Translator.translate(
								'message_from_x', {
									assignee	: msg.get('author_nickname')
								}
						));

						bubble.el.setTop(bubble.el.getTop() - difference);
					} else {
						icon.hide();
						body.hide();
						columns.show();

						field.focus();

						bubble.setTitle(Ext.ux.Translator.translate(
								'send_message_to_x', {
									assignee	: msg.get('author_nickname')
								}
						));

						bubble.el.setTop(bubble.el.getTop() + difference);
					};
				}, this);

		// hide the hud
		bubble.hide();

		// show the hud
		bubble.showHUD((hive === true) ? [0, -50] : [0, -15], 'b-t', 1,
				function() {
					bubble.positionPoker([0, 0], 't-b');
				}, true
		);

		return bubble;
	}
}
);

ExtMVC.OS.getOS().registerController('members',
		Kohive.controllers.MembersController
);


